package com.chenjia.proto.converter.benchmark;

import com.esotericsoftware.reflectasm.MethodAccess;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@State(Scope.Benchmark)
public class ReflectInvokeBenchmark {
    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(ReflectInvokeBenchmark.class.getSimpleName())
                .forks(1)
                .mode(Mode.Throughput)
                .warmupIterations(3)
                .measurementIterations(5)
                .build();

        new Runner(options).run();
    }

    private Method callMethod;
    private MethodAccess methodAccess;
    private int methodIndex;

    {
        try {
            callMethod = TestService.class.getMethod("call");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        methodAccess = MethodAccess.get(TestService.class);
        methodIndex = methodAccess.getIndex("call");
    }

    private final TestService service = new TestService();

    @Benchmark
    public int nativeCall() {
        return service.call();
    }

    @Benchmark
    public int fixCall() {
        return 0;
    }

    @Benchmark
    public int reflectCall() throws InvocationTargetException, IllegalAccessException {
        return (int) callMethod.invoke(service);
    }

    @Benchmark
    public int reflectAsmCall() {
        return (int) methodAccess.invoke(service, "call");
    }

    @Benchmark
    public int reflectAsmIndexCall() {
        return (int) methodAccess.invoke(service, methodIndex);
    }

}
/*
# 对比4种调用方式性能
Benchmark                               Mode  Cnt          Score                Error  Units
ReflectInvokeBenchmark.fixCall         thrpt    3  514209537.608 ± 1184526469.849       ops/s
ReflectInvokeBenchmark.nativeCall      thrpt    3  490100041.945 ±  819932862.848       ops/s
ReflectInvokeBenchmark.reflectAsmCall  thrpt    3  249391161.422 ±   14909275.016       ops/s
ReflectInvokeBenchmark.reflectCall     thrpt    3  165111366.331 ±  139516406.381       ops/s

# 增加方法复杂度：简单加法
Benchmark                               Mode  Cnt          Score            Error  Units
ReflectInvokeBenchmark.fixCall         thrpt    3  517042902.475 ± 1248102587.145  ops/s
ReflectInvokeBenchmark.nativeCall      thrpt    3  486678981.965 ±  893383073.205  ops/s
ReflectInvokeBenchmark.reflectAsmCall  thrpt    3  249486012.389 ±  113371744.514  ops/s
ReflectInvokeBenchmark.reflectCall     thrpt    3  152189113.410 ±  108905007.516  ops/s

# 预处理 index：性能几乎与反射调用差不多
Benchmark                                    Mode  Cnt          Score            Error  Units
ReflectInvokeBenchmark.fixCall              thrpt    3  513671695.733 ± 1171077731.639  ops/s
ReflectInvokeBenchmark.nativeCall           thrpt    3  444781601.712 ±  479162035.905  ops/s
ReflectInvokeBenchmark.reflectAsmCall       thrpt    3  246741718.441 ±   27033196.708  ops/s
ReflectInvokeBenchmark.reflectAsmIndexCall  thrpt    3  430942671.073 ±  759542795.744  ops/s
ReflectInvokeBenchmark.reflectCall          thrpt    3  154239284.444 ±  156659930.203  ops/s

# 借助 index 调用，能获得接近原生调用的性能
Benchmark                                    Mode  Cnt          Score          Error  Units
ReflectInvokeBenchmark.fixCall              thrpt    5  552815658.089 ± 10296012.498  ops/s
ReflectInvokeBenchmark.nativeCall           thrpt    5  522958446.022 ±  3959689.253  ops/s
ReflectInvokeBenchmark.reflectAsmCall       thrpt    5  282181908.511 ±  4678852.778  ops/s
ReflectInvokeBenchmark.reflectAsmIndexCall  thrpt    5  451250957.114 ±  5667211.781  ops/s
ReflectInvokeBenchmark.reflectCall          thrpt    5  152447631.172 ±  4754062.527  ops/s
 */